package web

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
)

type Context struct {
	Req         *http.Request
	Resp        http.ResponseWriter
	queryValues url.Values
	PathParams  map[string]string
	MatchRoute  string
	// 这个主要是为了个 middleware 读写用的
	RespData       []byte
	RespStatusCode int
	UserValues     map[string]any
}

type StringValue struct {
	val string
	err error
}

func (c *Context) BindJSON(val any) error {
	if val == nil {
		return errors.New("parse val can not be null")
	}

	if c.Req.Body == nil {
		return errors.New("request body can not be null")
	}

	decoder := json.NewDecoder(c.Req.Body)
	return decoder.Decode(val)
}

// FormValue
//
//	@Description: 获取表单参数
//	@receiver c
//	@param key
//	@return string
//	@return error
func (c *Context) FormValue(key string) StringValue {
	err := c.Req.ParseForm()
	if err != nil {
		return StringValue{
			err: err,
		}
		//return "", err
	}
	return StringValue{val: c.Req.FormValue(key)}
}

// QueryValue
//
//	@Description: 获取Query参数
//	@receiver c
//	@param key
//	@return string
//	@return error
func (c *Context) QueryValue(key string) StringValue {
	if c.queryValues == nil {
		// query底层会make 防止重复make
		c.queryValues = c.Req.URL.Query()
	}
	if !c.queryValues.Has(key) {
		return StringValue{
			err: errors.New(fmt.Sprintf("query value key [%s] not found", key)),
		}
	}
	return StringValue{
		val: c.queryValues.Get(key),
	}
}

// PathValues
//
//	@Description: 获取路由参数
//	@receiver c
//	@param key
//	@return string
//	@return error
func (c *Context) PathValues(key string) StringValue {
	val, ok := c.PathParams[key]
	if !ok {
		return StringValue{
			err: errors.New(fmt.Sprintf("path value key [%s] not found", key)),
		}
	}
	return StringValue{val: val}
}

func (c *Context) RespJson(code int, val any) error {
	jsonVal, err := json.Marshal(val)
	if err != nil {
		return err
	}

	c.Resp.Header().Set("Content-Type", "application/json")
	c.Resp.Header().Set("Content-Length", "1000")
	c.RespData = jsonVal
	c.RespStatusCode = code
	return err
}

// AsInt64
//
//	@Description: 转换数据为int64
//	@receiver s
//	@return int64
//	@return error
func (s StringValue) AsInt64() (int64, error) {
	if s.err != nil {
		return 0, s.err
	}
	return strconv.ParseInt(s.val, 10, 64)
}

// todo ... 后面更多的数据转换
